
/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

/**
 *
 * @author Administrator
 */
package hello;
import javax.bluetooth.*;
import javax.microedition.io.*;
import java.io.*;
import javax.microedition.lcdui.*;
import com.jcraft.jzlib.*;

public class BTProcessor implements Runnable{

    private DataOutputStream dataOutStream = null;
    private DataInputStream dataInStream = null;
    private StreamConnectionNotifier notifier=null;

    private HelloMIDlet mpParent=null;
    static private BTProcessor m_inst=null;

    public static BTProcessor GetInst()
    {
        if( m_inst == null )
        {
            m_inst = new BTProcessor();
            Thread t = new Thread( m_inst );
            t.start();
        }

        return m_inst;
    }

    public void setParent( HelloMIDlet parent )
    {
        mpParent = parent;
    }
    
    private BTProcessor()
    {
    }

    public int GetLittleEndianInt()
    {
        byte[] b = new byte[4];
        try
        {
            if( dataInStream != null )
            {
//                mpParent.bumpAlert("Begin to read!");
                
                b[0] = dataInStream.readByte();
                b[1] = dataInStream.readByte();
                b[2] = dataInStream.readByte();
                b[3] = dataInStream.readByte();
            }
            else
            {
                if( mpParent != null )
                    mpParent.bumpAlert( "dataInStream not inited!" );
            }
        }
        catch( java.io.EOFException e )
        {
            return -1;
        }
        catch( java.io.IOException e )
        {
//            if( mpParent != null )
//                mpParent.bumpAlert( e.toString() );
        }
        
        return (b[0] & 0xff) | ((b[1] << 8) & 0xff00) | ((b[2] << 24) >>> 8) | (b[3] << 24 );
        //return ByteBuffer.wrap( b ).getInt();
    }

    public void SendLittleEndianInt( int data )
    {
        try
        {
            dataOutStream.writeByte( data );
            dataOutStream.writeByte( data>>8 );
            dataOutStream.writeByte( data>>16 );
            dataOutStream.writeByte( data>>24 );
        }
        catch( java.io.IOException e )
        {
            if( mpParent != null )
                mpParent.bumpAlert( e.toString() );
        }
    }

    private void SendHelloPacket()
    {
        try
        {
            if( dataOutStream != null )
            {
                int width = mpParent.getCanvas().getClipWidth();
                int height = mpParent.getCanvas().getClipHeight();

                SendLittleEndianInt( 4 );
                SendLittleEndianInt( 16 );
                SendLittleEndianInt( width );
                SendLittleEndianInt( height );

                dataOutStream.flush();
            }
            else
            {
                if( mpParent != null )
                    mpParent.bumpAlert("Hasn't connected!");
            }
        }
        catch( java.io.IOException e )
        {
            if( mpParent != null )
                mpParent.bumpAlert( e.toString() );
        }

    }

    public void SendKeyEvent( int keycode , boolean isDown )
    {       
        try
        {
            if( dataOutStream != null )
            {
                mpParent.getCanvas().m_nowStatus = "Sending keycode:" + keycode;
                SendLittleEndianInt( 3 );
                SendLittleEndianInt( 16 );
                SendLittleEndianInt( isDown?1:0 );
                SendLittleEndianInt( keycode );
                mpParent.getCanvas().m_nowStatus = "End of Sending keycode:" + keycode;
                
                dataOutStream.flush();
            }
            else
            {
                if( mpParent != null )
                    mpParent.bumpAlert("Hasn't connected!");
            }
        }
        catch( java.io.IOException e )
        {
            if( mpParent != null )
                mpParent.bumpAlert( e.toString() );
        }
     }

    private void RegisterBTServer()
    {

        try
        {           // lets name our variables
        StreamConnection sconn = null;
        LocalDevice localdevice = null;
        ServiceRecord servicerecord = null;

        // step #1
        // the String url will already be defined with the
        // correct url parameters
        notifier = (StreamConnectionNotifier)Connector.open("btspp://localhost:09854B1CBCC64d2eBD6718DE9DE16F98;name=RemoteControl");

        // step #2
        // we will get the LocalDevice if not already done so
        localdevice = LocalDevice.getLocalDevice();
        servicerecord = localdevice.getRecord(notifier);

        // step #3 is optional

        // step #4
        // this step will block the current thread until
        // a client responds this step will also cause the
        // service record to be stored in the SDDB
        sconn =notifier.acceptAndOpen();

        dataOutStream =  sconn.openDataOutputStream();
        dataInStream  = sconn.openDataInputStream();

        //if( mpParent != null )
           // mpParent.bumpAlert("New client connected!");
        }
        catch( java.io.IOException e )
        {
            if( mpParent != null )
                mpParent.bumpAlert(e.toString());
        }
    }

    public void run()
    {
        try
        {
            mpParent.getCanvas().m_nowStatus = "Waiting for clients!";
            RegisterBTServer();
            mpParent.getCanvas().m_nowStatus = "New client connected!";
            SendHelloPacket();
            mpParent.getCanvas().m_nowStatus = "Sent Hello packet!";

            while( mpParent.running )
            {
                Thread.sleep(100);
                int type = GetLittleEndianInt();

                if( type != -1 )
                {
                    mpParent.getCanvas().m_nowStatus = "Got data Packet! Type:" + type;

                    switch( type )
                    {
                        case 5:
                        {
                            int length = GetLittleEndianInt();
                            int dataLength = length - 8;
//                            str = String.valueOf( "Datalength:" + dataLength );
//                            dataOutStream.writeChars( str );
//                            dataOutStream.flush();

                            byte b[] = new byte[dataLength];
                            int gotLength = 0;
                            while( gotLength < dataLength )
                            {
                                gotLength += dataInStream.read( b , gotLength , dataLength - gotLength );
                                mpParent.getCanvas().m_nowStatus = "TLength:" + dataLength + " RLength:" + gotLength;
                            }

                            byte[] unzippedBuffer = null;
                            try {
                            ByteArrayInputStream bis = new ByteArrayInputStream(b);
                            ZInputStream zip = new ZInputStream(bis);
                            byte[] buf = new byte[1024];
                            int num = -1;
                            ByteArrayOutputStream baos = new ByteArrayOutputStream();
                            while ((num = zip.read(buf, 0, buf.length)) != -1)
                            {
                                    baos.write(buf, 0, num);
                             }
                             unzippedBuffer = baos.toByteArray();
                             baos.flush();
                             baos.close();

                             zip.close();
                             bis.close();
                             mpParent.getCanvas().m_nowStatus = "Unzipped Length:" + unzippedBuffer.length;

                             mpParent.getCanvas().drawImg = Image.createImage( unzippedBuffer , 0 , unzippedBuffer.length );
                             }
                             catch (Exception ex)
                             {
                                mpParent.getCanvas().m_nowStatus = "Error while unzipping data!";
                                ex.printStackTrace();
                             }                            
                        }
                        break;
                    }
                }
            }
        }
        catch( java.io.IOException e )
        {
        }
        catch( java.lang.InterruptedException e )
        {

        }
    }

}
